/*
#define SQLITE_OK           0    Successful result 
#define SQLITE_ERROR        1    SQL error or missing database 
#define SQLITE_INTERNAL     2    An internal logic error in SQLite 
#define SQLITE_PERM         3    Access permission denied 
#define SQLITE_ABORT        4    Callback routine requested an abort 
#define SQLITE_BUSY         5    The database file is locked 
#define SQLITE_LOCKED       6    A table in the database is locked 
#define SQLITE_NOMEM        7    A malloc() failed 
#define SQLITE_READONLY     8    Attempt to write a readonly database 
#define SQLITE_INTERRUPT    9    Operation terminated by sqlite_interrupt() 
#define SQLITE_IOERR       10    Some kind of disk I/O error occurred 
#define SQLITE_CORRUPT     11    The database disk image is malformed 
#define SQLITE_NOTFOUND    12    (Internal Only) Table or record not found 
#define SQLITE_FULL        13    Insertion failed because database is full 
#define SQLITE_CANTOPEN    14    Unable to open the database file 
#define SQLITE_PROTOCOL    15    Database lock protocol error 
#define SQLITE_EMPTY       16    (Internal Only) Database table is empty 
#define SQLITE_SCHEMA      17    The database schema changed 
#define SQLITE_TOOBIG      18    Too much data for one row of a table 
#define SQLITE_CONSTRAINT  19    Abort due to contraint violation 
#define SQLITE_MISMATCH    20    Data type mismatch 
#define SQLITE_MISUSE      21    Library used incorrectly 
#define SQLITE_NOLFS       22    Uses OS features not supported on host 
#define SQLITE_AUTH        23    Authorization denied 
#define SQLITE_ROW         100   sqlite_step() has another row ready 
#define SQLITE_DONE        101   sqlite_step() has finished executing 
*/


#include "SQLiteHandler.h"
#include <stdio.h>

const	char*  sql_create_note			=	"create table note( _id INTEGER PRIMARY KEY autoincrement, json  TEXT, summary TEXT, createtime DOUBLE, modifytime DOUBLE, notifytime DOUBLE, status INTEGER, flg INTEGER,uuid TEXT )";
const	char*  sql_create_index_note	=	"Create unique index  idxnote_uuid  on  note( uuid )";  

const	char*  sql_create_tags			=	"create table tags( _id INTEGER PRIMARY KEY autoincrement, uuid  TEXT, name TEXT, isencode INTEGER, tapcount INTEGER, notecount INTEGER )";
const	char*  sql_create_index_tags_uuid	=	"Create unique index  idxtags_uuid  on  tags( uuid )";  
const	char*  sql_create_index_tags_name	=	"Create unique index  idxtags_name  on  tags( name )";


CSQLiteManager::CSQLiteManager() : m_pdb ( NULL ), m_maxcount(0)
{
	m_vec_qry.clear();
}

CSQLiteManager::~CSQLiteManager()
{
	size_t lSize = m_vec_qry.size();
	vector<CSQL_query*>::iterator it = m_vec_qry.begin();
	for( size_t i = 0; i < lSize; i++ )
	{
		if ( *it != NULL )
		{
			delete	(*it);
			*it	=	NULL;
		}
		
		it++;
	}

	m_vec_qry.clear();
}

int CSQLiteManager::Initialize( const char *_DBPath )
{
	if ( NULL == _DBPath )
	{
		return	XS_PARAM_NULL_POINTER;
	}

	if ( !IsDBExist( _DBPath ) )
	{
		CreateDB( _DBPath );
	}
	
	return	SQLiteOpen( &m_pdb, _DBPath );
}

int CSQLiteManager::UnInitialize()
{
	return	SQLiteClose( m_pdb );
}

int CSQLiteManager::Query_Create( int* _pqh, CSQL_query** _ppq, sqlite3* _pdb )
{
	int	iRlt	=	XS_SUCCESS;


	do {
		if( NULL == _ppq || NULL == _pqh ){
			iRlt	=	XS_PARAM_NULL_POINTER;
			break;
		}
		if ( NULL == _pdb )
		{
			*_ppq	= new CSQL_query( m_pdb, ++m_maxcount );
		}
		else
		{
			*_ppq	= new CSQL_query( _pdb, ++m_maxcount );
		}
		
		*_pqh	= m_maxcount;

		if ( *_ppq == 0 )	break;

		m_vec_qry.push_back( *_ppq );


	}	while (false);


	return	iRlt;
}

int CSQLiteManager::Query_Delete( int _qh )
{

	int	iRlt	=	XS_SUCCESS;
	vector<CSQL_query*>::iterator itor = m_vec_qry.begin();

	for (  ; itor != m_vec_qry.end(); itor++ )
	{
		if ((*itor)->GetQh() == _qh)
		{
			delete	(*itor);
			m_vec_qry.erase(itor);
			break;
		}
	}

	return	iRlt;
}

bool CSQLiteManager::IsDBExist( const char *_DBPath )
{
	bool	bflg	=	false;
	do 
	{
		FILE *fp	=	fopen( _DBPath, "rb" );
		if ( NULL == fp )
		{
			bflg	=	false;
			break;
		}
		
		fclose( fp );

		if ( !IsDBEffective( _DBPath ) )
		{
			bflg	=	false;
			break;
		}

		bflg	=	true;

	} while ( false );

	return	bflg;
}

int CSQLiteManager::CreateDB( const char *_DBPath )
{
	int			iRlt	=	XS_SUCCESS;
	int			*p		=	NULL;
	sqlite3*	pdb		=	NULL;

	iRlt	=	SQLiteOpen( &pdb, _DBPath );
	if ( iRlt != XS_SUCCESS )
	{
		return	iRlt;
	}

	do 
	{
		iRlt	=	execute_sql( sql_create_note, 0, p, pdb );

		iRlt	=	execute_sql( sql_create_index_note, 0, p, pdb );

		iRlt	=	execute_sql( sql_create_tags, 0, p, pdb );

		iRlt	=	execute_sql( sql_create_index_tags_name, 0, p, pdb );
		iRlt	=	execute_sql( sql_create_index_tags_uuid, 0, p, pdb );

	} while ( false );


	SQLiteClose( pdb );

	return	iRlt;
}

bool CSQLiteManager::IsDBEffective( const char *_DBPath )
{
	return	true;
}

int CSQLiteManager::SQLiteOpen( sqlite3** _ppdb, const char * _DBPath )
{
	int	iRlt	=	XS_SUCCESS;

	iRlt	=	sqlite3_open( _DBPath, _ppdb );
	if( SQLITE_OK != iRlt )
	{
		iRlt	=	XS_SQLITE_OPEN_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}

	return	iRlt;
}

int CSQLiteManager::SQLiteClose( sqlite3* _pdb )
{
	int	iRlt	=	XS_SUCCESS;

	iRlt	=	sqlite3_close( m_pdb );
	if( SQLITE_OK != iRlt )
	{
		iRlt	=	XS_SQLITE_CLOSE_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}


	return	XS_SUCCESS;
}

int CSQLiteManager::GetLastRowid()
{
	if ( NULL == m_pdb )
	{
		return	-1;
	}

	return	(int)sqlite3_last_insert_rowid( m_pdb );
}


//////////////////////////////////////////////////////////////////////////

CSQL_query::CSQL_query( sqlite3* _pdb, int _qh ) : 
m_pdb(0), m_pstmt(0), m_qh(_qh), m_SQLite_Error(0)
{
	m_pdb	= _pdb;
}

CSQL_query::~CSQL_query()
{
	if( NULL != m_pstmt )
	{	
		Finalize();
	}
}

int CSQL_query::Prepare( const char* _pcsQuery )
{

	int	iRlt	=	XS_SUCCESS;

	if( ( NULL == _pcsQuery ) || ( NULL != m_pstmt ) || ( NULL == m_pdb ) )
	{
		return	XS_PARAM_NULL_POINTER;
	}

	iRlt	=	sqlite3_prepare_v2 ( m_pdb, _pcsQuery, -1, &m_pstmt, 0 );
	if ( iRlt != SQLITE_OK )
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_QUREY_CREATE_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}

	return				iRlt;
}

int CSQL_query::Finalize()
{
	int	iRlt	=	XS_SUCCESS;

	iRlt	= sqlite3_finalize( m_pstmt );
	if (iRlt != SQLITE_OK)
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_FINALIZE_ERROR;
	}
	else
	{
		m_pstmt = NULL;
		iRlt	=	XS_SUCCESS;
	}
	
	return	iRlt;
}

int CSQL_query::Reset()
{
	int	iRlt	=	XS_SUCCESS;

	if ( NULL == m_pstmt )
	{
		return	XS_RESET_ERROR;
	}

	iRlt	= sqlite3_reset( m_pstmt );
	if ( iRlt != SQLITE_OK )
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_RESET_ERROR;
	}	
	else
	{
		iRlt	=	XS_SUCCESS;
	}

	return	iRlt;
}

int CSQL_query::Step()
{
	int	iRlt	=	XS_SUCCESS;

	if( m_pstmt == NULL )
	{
		return	XS_STEP_ERROR;
	}

	iRlt	= sqlite3_step( m_pstmt );
	if( SQLITE_DONE == iRlt )
	{
		iRlt = XS_STEP_DONE;	
	}
	else if( SQLITE_ROW == iRlt )
	{
		iRlt = XS_STEP_ROW;
	}
	else
	{
		sqlite3_reset( m_pstmt );
		iRlt	=	XS_STEP_ERROR;
	}

	return		iRlt;
}

int CSQL_query::GetField( long _lIndex, int* _plValue )
{

	if ( NULL == m_pstmt || NULL == _plValue )
	{
		return XS_PARAM_NULL_POINTER;
	}

	*_plValue	=	sqlite3_column_int(	m_pstmt, _lIndex );

	return	XS_SUCCESS;
}

int CSQL_query::GetField( long _lIndex, double* _pdValue )
{
	if ( NULL == m_pstmt || NULL == _pdValue )
	{
		return XS_PARAM_NULL_POINTER;
	}

	*_pdValue	=	sqlite3_column_double(	m_pstmt, _lIndex );

	return	XS_SUCCESS;
}

int CSQL_query::GetField( long _lIndex, char** _ppcvalue )
{
	if ( NULL == m_pstmt || NULL == _ppcvalue )
	{
		return XS_PARAM_NULL_POINTER;
	}

	*_ppcvalue	=	(char*)sqlite3_column_text( m_pstmt, _lIndex );

	return	XS_SUCCESS;
}

int CSQL_query::Getblob( long _lIndex, const void** _ppvalue )
{
	if ( NULL == m_pstmt || NULL == _ppvalue )
	{
		return XS_PARAM_NULL_POINTER;
	}

	*_ppvalue	=	sqlite3_column_text( m_pstmt, _lIndex );

	return	XS_SUCCESS;
}

int CSQL_query::Bindblob( long _lIndex, void* _pvalue , int isize )
{
	int	iRlt	=	XS_SUCCESS;

	if ( NULL == m_pstmt )
	{
		return	XS_PARAM_NULL_POINTER;
	}

	iRlt	= sqlite3_bind_blob( m_pstmt,  _lIndex,  _pvalue, isize, NULL );
	if ( iRlt != SQLITE_OK )
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_BIND_BLOB_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}


	return	iRlt;
}

int CSQL_query::Bind( long _lindex, double _dvalue )
{
	int	iRlt	=	XS_SUCCESS;

	if ( NULL == m_pstmt )
	{
		return	XS_PARAM_NULL_POINTER;
	}

	iRlt	= sqlite3_bind_double( m_pstmt,  _lindex,  _dvalue  );
	if ( iRlt != SQLITE_OK )
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_BIND_DOUBLE_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}


	return	iRlt;
}

int CSQL_query::Bind( long _lIndex )
{
	int	iRlt	=	XS_SUCCESS;

	if ( NULL == m_pstmt )
	{
		return	XS_PARAM_NULL_POINTER;
	}

	iRlt	= sqlite3_bind_null( m_pstmt,  _lIndex );
	if ( iRlt != SQLITE_OK )
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_BIND_NULL_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}


	return	iRlt;
}

int CSQL_query::Bind( long _lindex, int _lvalue )
{
	int	iRlt	=	XS_SUCCESS;

	if ( NULL == m_pstmt )
	{
		return	XS_PARAM_NULL_POINTER;
	}

	iRlt	=	sqlite3_bind_int( m_pstmt,  _lindex,  _lvalue );
	if ( iRlt != SQLITE_OK )
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_BIND_LONG_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}


	return	iRlt;
}

int CSQL_query::Bind ( long _lIndex, char* _pcvalue , int isize )
{
	int	iRlt	=	XS_SUCCESS;

	if ( NULL == m_pstmt )
	{
		return	XS_PARAM_NULL_POINTER;
	}

	iRlt	=	sqlite3_bind_text( m_pstmt,  _lIndex,  _pcvalue, isize, NULL );
	if ( iRlt != SQLITE_OK )
	{
		m_SQLite_Error	=	iRlt;
		iRlt	=	XS_BIND_LONG_ERROR;
	}
	else
	{
		iRlt	=	XS_SUCCESS;
	}


	return	iRlt;
}
